#pragma once

#include <atomic>
#include <thread>

// naive implementation of Test-And-Set (TAS) spinlock

class tas_spinlock {
public:
    tas_spinlock()
        : locked_(false)
    {}

    tas_spinlock(const tas_spinlock& that) = delete;
    tas_spinlock& operator =(const tas_spinlock& that) = delete;

    void lock() {
        while (locked_.exchange(true, std::memory_order_acquire)) {
            std::this_thread::yield();
        }
    }

    bool try_lock() {
        return !locked_.exchange(true, std::memory_order_acquire);
    }

    void unlock() {
        locked_.store(false, std::memory_order_release);
    }

private:
    std::atomic<bool> locked_;
};

